/**
 * 版权所有：版权所有(C) 2016，卓信金控
 * 系统名称：FOL
 * @ClassName: PoiCommUtil
 * 模块名称：
 * @Description: 内容摘要：导出word文档的帮助类
 * @author Guanxu
 * @date 2018年3月21日
 * @version V1.0
 * history:
 * 1、2018年3月21日 Guanxu 创建文件
 */

package com.zx.sframe.util.poi;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcBorders;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;

import com.google.gson.Gson;
import com.zx.emanage.util.gen.GlobalVal;
import com.zx.emanage.util.gen.StringUtil;
import com.zx.platform.syscontext.PlatformGlobalVar;
import com.zx.sframe.util.openoffice.LibreOfficeUtil;

/**
 * 类 名 称:PoiCommUtil
 *
 * 内容摘要: 
 *
 * 作 者:Baisong
 */
public class PoiCommUtil
{
	/**
	 * 
	  * @Title: main
	  * @Description: main
	  * @param @param args
	  * @return void
	  * @author: wangyihan
	  * @time: 2020年9月17日 下午1:20:38
	  * history:
	  * 1、2020年9月17日 下午1:20:38 wangyihan 创建方法
	  *
	 */
    public static void main(String args[])
    {
        Map<String, Object> m = new HashMap<String, Object>();
        m.put("user_phone_", "13654215988");
        String tmp = "$IMG{a,200,200}";
        String img_info = tmp.substring(5, tmp.length() - 1);
        System.out.println(img_info);
        String s = "{\"house_address_all\":\"沈阳市沈河区和平南大街180号C2\",\"refund_limit_month_tz\":\"18,900.00\",\"appro_limit_lower\":\"1000000.00\",\"loan_bank_of_deposit_name\":\"中信银行沈阳北站支行\",\"lt_nine\":0,\"first_guarantee_postal_address\":\"沈阳市沈河区和平南大街180号C2-29-2\",\"house_vol_no_all\":\"沈房产权属卷号100-7号\",\"first_guarantee_mobile_phone\":\"13652141254\",\"borrow_deadline_fcj\":\"24\",\"refund_name\":\"王超群\",\"real_borrow_interest_is_gt_zero\":1,\"lender_name\":\"王超群\",\"debtor_loan_number\":\"1234 5678 9789 4500\",\"estate_value\":\"1050000.00\",\"protocol_place_sign\":\"沈阳市沈河区\",\"borrow_end_date_fcj\":\"2020-04-15\",\"is_not_special_AB\":\"1\",\"appro_limit_lower_1\":\"1,000,000.00\",\"cash\":\"48900.00\",\"fee_borrow_interest\":0,\"id_card_real\":\"123456789987456123\",\"first_repayment_date\":\"2018-05-15\",\"loan_apply_remark\":\"\",\"postal_address\":\"沈阳市沈河区和平南大街180号C2-29-1\",\"lender_name_all\":\"王超群\",\"gt_thirty-six_lt_eq_seventy-two\":0,\"loan_amount_caps\":\"玖拾伍万壹仟壹佰元整\",\"guarantee_name_str\":\"刘禹锡\",\"dkrInfoList\":[{\"salesman_name\":\"白松 101057\",\"customer_modu\":\"dk\",\"mobile_phone_str\":\"13654121245\",\"gender\":\"1\",\"create_user_name\":\"白松 101057\",\"customer_channel\":\"1\",\"id_card\":\"**************6123\",\"customer_category\":\"3\",\"ifc_cre_loan_head_id\":264,\"customer_category_name\":\"成单客户\",\"salesman_id\":123,\"customer_status_name\":\"生效中\",\"create_timestamp\":\"2018-04-16\",\"last_update_timestamp\":\"Apr 16, 2018 9:48:13 AM\",\"mobile_phone\":\"*******1245\",\"customer_source_name\":\"IFC\",\"ifc_cus_customer_head_id\":461,\"salesman_city_code\":\"0024\",\"customer_source\":\"IFC\",\"ifc_cus_customer_head_id_in\":335,\"customer_code\":\"PHKH20171200005\",\"id_card_real\":\"123456789987456123\",\"salesman_shortcode\":\"101057\",\"postal_address\":\"沈阳市沈河区和平南大街180号C2-29-1\",\"create_user_id\":123,\"enable_flag\":\"1\",\"customer_channel_name\":\"一手客户\",\"salesman_dept_id\":11,\"last_update_user_id\":123,\"create_user_shortcode\":\"101057\",\"is_sign\":\"1\",\"customer_age\":\"-5881\",\"is_major\":\"1\",\"customer_status\":\"1\",\"customer_name\":\"刘邦\"}],\"fee_principal_caps\":\"\",\"gt_eq_nine\":1,\"loan_amount\":\"951100.00\",\"debtor_loan_bank\":\"招商银行\",\"refund_bank_all\":\"中信银行沈阳北站支行\",\"refund_limit_month\":18900.00000000,\"is_special_A\":\"0\",\"is_self_debit_card\":\"0\",\"fee_principal_lower_1\":\"\",\"is_special_B\":\"0\",\"is_have_B_flag\":\"0\",\"refund_number\":\"6217 7329 0115 8448\",\"protocol_year\":\"2018\",\"every_month_refund_money\":\"18900.00\",\"borrow_deadline\":12,\"lender_mobile_phone\":\"15802451112\",\"default_interest_fee\":\"5000.00\",\"real_borrow_interest\":\"0.89\",\"principal_lower\":1000000.00000000,\"appro_limit_capital\":\"壹佰万元整\",\"house_owner_all\":\"\",\"platform_rate\":\"0.49\",\"lender_id_card\":\"21010419870313431X\",\"principal_caps\":\"壹佰万元整\",\"borrow_end_date\":\"2019年04月15日\",\"gt_seventy-two\":0,\"customer_name_all\":\"刘邦、张三\",\"gt_six\":1,\"product_repayment_type\":\"先息后本\",\"house_no_all\":\"沈房产权属证号100\",\"service_fee_fourth_num\":\"2.4\",\"lender_contact_address\":\"沈阳市大东区东辽街16号3-1-2\",\"second_repayment_date\":\"2018-06-15\",\"loan_apply_remark_forCC\":\"第一顺序\",\"liquidated_fee\":\"0.066%\",\"principal_lower_1\":\"1,000,000.00\",\"is_company_specified_account\":\"1\",\"fee_principal_lower\":\"0.00\",\"gt_three\":1,\"ifcCreLoanProtocolGuaranteeInfoList\":[{\"ifc_cre_loan_protocol_guarantee_info_id\":14,\"create_user_id\":123,\"guarantee_postal_address\":\"沈阳市沈河区和平南大街180号C2-29-2\",\"create_user_name\":\"白松\",\"guarantee_customer_name\":\"刘禹锡\",\"enable_flag\":\"1\",\"second_current_address\":\"沈阳市沈河区和平南大街180号C2-29-3\",\"ifc_cre_loan_protocol_info_id\":118,\"guarantee_com_loan_relation\":\"父子\",\"create_user_shortcode\":\"101057\",\"create_timestamp\":\"Apr 16, 2018 10:17:39 AM\",\"guarantee_mobile_phone\":\"13652141254\",\"guarantee_id_card\":\"210727198501051234\"}],\"refund_bank\":\"中信\",\"lt_eq_thirty\":1,\"protocol_date\":\"2018年04月16日\",\"refund_day\":\"15\",\"gdrInfoList\":[],\"debtor_loan_name\":\"刘邦\",\"is_not_have_B_flag\":\"1\",\"debtor_loan_bank_all\":\"招商银行南塔支行\",\"customer_id_card_all\":\"123456789987456123\",\"house_building_area_all\":\"100.25m²\",\"loan_card_no\":\"6217 7329 0115 8448\",\"lt_eq_three\":0,\"fee_liquidated_day_money\":0,\"real_interest_multiply_deadline\":\"10.68\",\"refund_bank_branch\":\"中信银行沈阳北站支行\",\"lt_eq_six\":0,\"follow_loan_money\":\"100,000.00\",\"zdr_phone_str\":\"13654121245\",\"commission_rate\":\"3.00\",\"customer_name\":\"刘邦\",\"borrow_interest\":\"1.00\",\"protocol_id_year_num\":\"SY2018041601\",\"customer_phone_all\":\"13654121245\"}";
        Gson gson = new Gson();
        m = gson.fromJson(s, Map.class);
        try
        {
            replaceWordValueByMap("I:\\3.docx", m);
            LibreOfficeUtil.libreOfficeToPDF("I:\\3.docx", "I:\\5.pdf");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }


    /**
     * 
     * @Title: replaceWordValueByMap
     * @Description: 替换传入文件的特殊符合为指定文字
     * $P{}普通字符替换，表格里需要替换的字符也使用此类标识；
     * $P{checkbox_}为特殊字符会更换为checkbox，如果值为1则为选中状态，0为未选中状态
     * $TB{为表格第一行的为可变表格，内容以表格本身为基础，根据传入List的size进行处理，表格本身内容的替换与$P{}相同
     * $TBN{表格复制后不再插入空白行
     * $TB_0,1{表格的第0,1个cell不再进行复制
     * $P{checkrm_}为特殊字符，出入值为1，则删除当前行。
     * @param inFile 原文件路径
     * @param param 特殊字符对应的文字内容
     * @throws Exception 
     * @author: Guanxu
     * @time:2018年3月21日 下午4:20:38
     * history:
     * 1、2018年3月21日 Guanxu 创建方法
     */
    public static void replaceWordValueByMap(String inFile, Map<String, Object> param) throws Exception
    {
        InputStream is = new FileInputStream(inFile);
        CustomXWPFDocument document;
        try
        {
            document = new CustomXWPFDocument(OPCPackage.open(is));
            // 替换段落里面的变量
            if (param != null && param.size() > 0)
            {
                // 处理段落
                List<XWPFParagraph> paragraphList = document.getParagraphs();
                processParagraphs(paragraphList, param);
                handleTable(document, param);
            }
            OutputStream os = new FileOutputStream(inFile);
            document.write(os);
            close(os);
            close(is);
        }
        catch (Exception e)
        {

            e.printStackTrace();
        }
    }

    /**
     * 
      * @Title: insertPicture
      * @Description: insertPicture
      * @param @param document
      * @param @param filePath
      * @param @param inline
      * @param @param width
      * @param @param height
      * @param @throws Exception
      * @return void
      * @author: wangyihan
      * @time: 2020年9月17日 下午1:23:51
      * history:
      * 1、2020年9月17日 下午1:23:51 wangyihan 创建方法
      *
     */
    public static void insertPicture(XWPFDocument document, String filePath, CTInline inline, int width, int height) throws Exception
    {
        int id = document.getAllPictures().size() - 1;
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        @SuppressWarnings("deprecation")
		String blipId = document.getAllPictures().get(id).getPackageRelationship().getId();
        String picXml = "" + "" + "   " + "      " + "         " + "           " + id + "\" name=\"Generated\"/>" + "            " + "         " + "         " + "           " + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" + "            " + "               " + "            " + "         " + "         " + "            " + "               " + "              " + width + "\" cy=\"" + height + "\"/>" + "            " + "            " + "               " + "            " + "         " + "      " + "   " + "";
        inline.addNewGraphic().addNewGraphicData();
        XmlToken xmlToken = null;
        try
        {
            xmlToken = XmlToken.Factory.parse(picXml);
        }
        catch (XmlException xe)
        {
            xe.printStackTrace();
        }
        inline.set(xmlToken);
        inline.setDistT(0);
        inline.setDistB(0);
        inline.setDistL(0);
        inline.setDistR(0);
        CTPositiveSize2D extent = inline.addNewExtent();
        extent.setCx(width);
        extent.setCy(height);
        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
        docPr.setId(id);
        docPr.setName("IMG_" + id);
        docPr.setDescr("IMG_" + id);
    }

    /** 
     * 根据图片类型，取得对应的图片类型代码 
     * @param picType 
     * @return int 
     */
    private static int getPictureType(String picType)
    {
        int res = CustomXWPFDocument.PICTURE_TYPE_PICT;
        // 判断
        if (picType != null)
        {
        	// 判断
            if (picType.equalsIgnoreCase("png"))
            {
                res = CustomXWPFDocument.PICTURE_TYPE_PNG;
            }
            // 判断
            else if (picType.equalsIgnoreCase("dib"))
            {
                res = CustomXWPFDocument.PICTURE_TYPE_DIB;
            }
            // 判断
            else if (picType.equalsIgnoreCase("emf"))
            {
                res = CustomXWPFDocument.PICTURE_TYPE_EMF;
            }
            // 判断
            else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg"))
            {
                res = CustomXWPFDocument.PICTURE_TYPE_JPEG;
            }
            // 判断
            else if (picType.equalsIgnoreCase("wmf"))
            {
                res = CustomXWPFDocument.PICTURE_TYPE_WMF;
            }
        }
        return res;
    }

    /**
     * 
     * @Title: handleImg
     * @Description: 替换图片$IMG{id,width,height}
     * @param document
     * @param param 
     * @author: Guanxu
     * @time:2018年6月6日 上午11:01:57
     * history:
     * 1、2018年6月6日 Guanxu 创建方法
     */
    private static void handleImg(XWPFParagraph xwpfparagraph,int run_index, XWPFRun run, Map<String, Object> param, String key)
    {
        
        String tmp = run.getText(0);
        System.out.println(tmp);
        // 判断
        if (tmp.indexOf("IMG") > -1)
        {
            Integer img_width = 100;
            Integer img_height = 50;
        	String img_id = "";
            // 判断
            if(StringUtils.isEmpty(key))
            {
            	String img_info[] = tmp.substring(7, tmp.length() - 1).split(",");
            	img_id = img_info[0];
            }
            else
            {
            	img_id = key.replace("IMG_", "");
            }
          
            String url = GlobalVal.getProperty("upload_file_url_template") + (String) param.get(img_id);
            // 判断
            if(StringUtil.isNotBlank(url)) 
            {
                try
                {
                	run.setText("", 0);
                	
                    InputStream is = getFileInputStream(url);
                    String picType = url.substring(url.lastIndexOf(".") + 1);
                    File file = new File(copyFile(is, picType));
                    System.out.println(img_width + "->" + img_height);
                    InputStream fis = new FileInputStream(file);
                    run.addPicture(fis, getPictureType(picType), "test.jpg", Units.toEMU(img_width), Units.toEMU(img_height));
                    fis.close();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @Title: getImgWidth
     * @Description: getImgWidth
     * @param is 
     * @author: Guanxu
     * @time:2018年6月7日 上午10:31:51
     * history:
     * 1、2018年6月7日 Guanxu 创建方法
    */
    @SuppressWarnings("unused")
	private static int[] getImgWidth(File file)
    {
        BufferedImage src = null;
        int[] res = new int[2];
        try
        {
            InputStream is = new FileInputStream(file);
            src = javax.imageio.ImageIO.read(is);
            // 得到源图宽
            int width = src.getWidth(null); 
            int height = src.getHeight(null);
            res[0] = width;
            res[1] = height;
            is.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return res;

    }

    /**
     * 
      * @Title: copyFile
      * @Description: copyFile
      * @param @param fis
      * @param @param picType
      * @param @return
      * @return String
      * @author: wangyihan
      * @time: 2020年9月17日 下午1:24:42
      * history:
      * 1、2020年9月17日 下午1:24:42 wangyihan 创建方法
      *
     */
    private static String copyFile(InputStream fis, String picType)
    {
        String file_name = UUID.randomUUID() + "." + picType;
        String copy_template_path = GlobalVal.getProperty("realDownloadPath") + "/" + file_name;
        // String copy_template_path = "D://" + file_name;

        // 复制文件
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        OutputStream fos = null;
        try
        {
            bis = new BufferedInputStream(fis);
            fos = new FileOutputStream(copy_template_path);
            bos = new BufferedOutputStream(fos);

            int byteRead = 0;
            byte[] buffer = new byte[8192];
            while ((byteRead = bis.read(buffer, 0, 8192)) != -1)
            {
                bos.write(buffer, 0, byteRead);
            }

            bos.flush();
            fis.close();
            bis.close();
            fos.close();
            bos.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return copy_template_path;
    }

    /**
     * 
      * @Title: getFileInputStream
      * @Description: getFileInputStream
      * @param @param url_str
      * @param @return
      * @return InputStream
      * @author: wangyihan
      * @time: 2020年9月17日 下午1:24:52
      * history:
      * 1、2020年9月17日 下午1:24:52 wangyihan 创建方法
      *
     */
    private static InputStream getFileInputStream(String url_str)
    {
        try
        {
            URL url = new URL(url_str);
            // 打开链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置请求方式为"GET"
            conn.setRequestMethod("GET");
            // 超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);

            String messagePic = conn.getHeaderField(0);// 文件存在‘HTTP/1.1 200
            // OK’ 文件不存在
            // ‘HTTP/1.1 404 Not
            // Found’
            if (messagePic.startsWith("HTTP/1.1 200"))
            {
                return conn.getInputStream();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 
     * @Title: processParagraphs
     * @Description: 根据map替换文件中出现的$P{}内容
     * @param paragraphList
     * @param param
     * @throws Exception 
     * @author: Guanxu
     * @time:2018年3月21日 下午3:23:56
     * history:
     * 1、2018年3月21日 Guanxu 创建方法
     */
    private static String processParagraphs(List<XWPFParagraph> paragraphList, Map<String, Object> param) throws Exception
    {
    	// 判断
        if (paragraphList != null && paragraphList.size() > 0)
        {
            // 遍历所有段落
            for (XWPFParagraph paragraph : paragraphList)
            {
                List<XWPFRun> runs = paragraph.getRuns();
                // 判断
                for (int j = 0;j<runs.size();j++)
                {
                    XWPFRun run = runs.get(j);
                    String text = run.getText(0);
                    System.out.println(text);
                    // 判断
                    if (text != null && text.indexOf("$P{") > -1 && text.indexOf("}") > -1)
                    {
                        String key = text.substring(text.indexOf("{") + 1, text.indexOf("}"));
                        String val = param.get(key) == null ? "" : "" + param.get(key);
                        
                        // 判断
                        if(text.indexOf("<cutting>") > -1)
                        {
                        	// 判断
                        	if(param.get("is_replace_dynamic_param_flag") != null && new Boolean(param.get("is_replace_dynamic_param_flag").toString()))
                        	{
                        		continue;
                        	}
                            
                        	String[] arr = text.split("<cutting>");
                        	text = text.replace("<cutting>", "<br>");
                        	// 循环替换参数
                        	for(String s : arr)
                        	{
                        		String tmp_key = s.substring(s.indexOf("{") + 1, s.indexOf("}"));
                                String tmp_val = param.get(tmp_key) == null ? "" : "" + param.get(tmp_key);
                        		// 判断
                                if (tmp_key.startsWith("IMG"))
                                {
                                	run.addBreak();
                                    handleImg(paragraph, j, run, param, tmp_key);
                                    text = text.replace("$P{" + tmp_key + "}", "");
                                }
                        		else
                        		{
                        			text = text.replace("$P{" + tmp_key + "}", tmp_val);
                        		}
                        	}
                        	run.setText(text, 0);
                        	
                        	// 判断
                            if (text.indexOf("<br>") > -1)
                            {
                                String[] line_text = text.split("<br>");
                                // 循环
                                for (int i = 0; i < line_text.length; i++)
                                {
                                	// 判断
                                    if (i == 0)
                                    {
                                        run.setText(line_text[i], 0);
                                    }
                                    else
                                    {
                                        run.setText(line_text[i]);
                                    }
                                    run.addBreak();
                                }
                            }
                            else
                            {
                                run.setText(text, 0);
                            }
                        }
                        // 判断
                        else if (key.startsWith("checkrm"))
                        {
                        	// 判断
                        	if(param.get("is_replace_dynamic_param_flag") != null && new Boolean(param.get("is_replace_dynamic_param_flag").toString()))
                        	{
                        		continue;
                        	}
                        	
                            val = param.get(key.substring(8)) == null ? "" : "" + param.get(key.substring(8));
                            
                            // 判断
                            if (val.equals("0"))
                            {
                                return "remove";
                            }
                            else
                            {
                                val = "";
                            }
                        }
                        // 判断
                        else if (key.startsWith("checkbox"))
                        {
                        	// 判断
                        	if(param.get("is_replace_dynamic_param_flag") != null && new Boolean(param.get("is_replace_dynamic_param_flag").toString()))
                        	{
                        		continue;
                        	}
                        	
                            val = param.get(key.substring(9)) == null ? "" : "" + param.get(key.substring(9));
                            
                            // 判断
                            if (val.equals("1"))
                            {
                                run.setText(text.replace("$P{" + key + "}", "☑"), 0);
                            }
                            else
                            {
                                run.setText(text.replace("$P{" + key + "}", "☐"), 0);
                            }
                        }
                        // 判断
                        else if (key.startsWith("IMG"))
                        {
                            handleImg(paragraph, j, run, param, null);
                        }
                        else
                        {
                        	// 判断
                            if (val == null || val.trim().length() == 0)
                            {
                            	// 判断
                            	if(param.get("is_replace_dynamic_param_flag") != null && new Boolean(param.get("is_replace_dynamic_param_flag").toString()))
                            	{
                            		continue;
                            	}
                            	else
                            	{
                            		val = "      ";
                            	}
                                
                            }
                            
                            text = text.replace("$P{" + key + "}", val);
                            
                            // 判断
                            if (text.indexOf("<br>") > -1)
                            {
                                String[] line_text = text.split("<br>");
                                // 循环
                                for (int i = 0; i < line_text.length; i++)
                                {
                                	// 判断
                                    if (i == 0)
                                    {
                                        run.setText(line_text[i], 0);
                                    }
                                    else
                                    {
                                        run.setText(line_text[i]);
                                    }
                                    run.addBreak();
                                }
                            }
                            else
                            {
                                run.setText(text, 0);
                            }
                        }
                    }
                }
            }
        }
        return "ok";
    }

    /**
     * 
     * @Title: handleTable
     * @Description: 处理表格中的数据，如果表格第一行以$TB{开头，则为可变表格，需要根据传人的list进行处理
     * 其余时候直接替换表格中出现的$P{}内容
     * @param xwpf
     * @param param 
     * @author: Guanxu
     * @time:2018年3月21日 下午3:29:01
     * history:
     * 1、2018年3月21日 Guanxu 创建方法
     */
    public static void handleTable(XWPFDocument xwpf, Map<String, Object> param)
    {
        try
        {
            Iterator<XWPFTable> it = xwpf.getTablesIterator();// 得到word中的表格

            while (it.hasNext())
            {

                XWPFTable table = it.next();
                List<XWPFTableRow> rows = table.getRows();
                // 查看非可变表格中是否有需要替换的数据
                List<Integer> removeRowIds = new ArrayList<>();
                List<Integer> variable_row_list = new ArrayList<>();
                // 循环
                for (int k = 0; k < rows.size(); k++)
                {
                    XWPFTableRow row = rows.get(k);
                    List<XWPFTableCell> cells = row.getTableCells();
                    // 循环
                    for (int j = 0; j < cells.size(); j++)
                    {
                        XWPFTableCell cell = cells.get(j);
                        // 获取表格的标题
                        String text = cell.getText();
                        // 判断
                        if (text != null && text.startsWith("$TB"))
                        {

                            String variable_row_count = text.substring(text.indexOf("(") + 1, text.indexOf(")"));
                            int row_count = new Integer(variable_row_count);
                            variable_row_list.add(k);
                            k = k + row_count;
                            break;
                        }
                        // 判断
                        if (text != null && text.trim().length() > 0)
                        {

                            try
                            {
                                String result = processParagraphs(cell.getParagraphs(), param);
                                // 判断
                                if ("remove".equals(result))
                                {
                                    removeRowIds.add(k);

                                }
                            }
                            catch (Exception e)
                            {
                                e.printStackTrace();
                            }
                        }

                    }
                }
                // 循环
                for (int i = removeRowIds.size() - 1; i >= 0; i--)
                {

                    table.removeRow(removeRowIds.get(i));
                }
                int new_row_count = 0;
                // 循环
                for (int i = 0; i < variable_row_list.size(); i++)
                {
                    new_row_count = handleChangedTB(table, param, variable_row_list.get(i) + new_row_count);
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 
     * @Title: handleChangedTB
     * @Description: 处理可变表格数据
     * @param table
     * @param tb_list_name
     * @param tb_map 
     * @author: Guanxu
     * @param k2 
     * @time:2018年3月21日 下午4:00:56
     * history:
     * 1、2018年3月21日 Guanxu 创建方法
     */
    private static int handleChangedTB(XWPFTable table, Map<String, Object> tb_map, int begin_index)
    {
        String tb_list_name = table.getRow(begin_index).getCell(0).getText();
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> tbList = (List<Map<String, Object>>) tb_map.get(tb_list_name.substring(tb_list_name.indexOf("{") + 1, tb_list_name.indexOf("}")));
        // 判断
        if (tbList == null)
        {
            tbList = new ArrayList<>();
        }
        String tb_name = tb_list_name.substring(0, tb_list_name.indexOf("{"));
        String no_copy_cell = "";
        // 判断
        if (tb_name.indexOf("_") > -1)
        {
            no_copy_cell = tb_list_name.substring(tb_list_name.indexOf("_") + 1, tb_list_name.indexOf("{"));
        }
        tb_name = tb_list_name.substring(0, tb_list_name.indexOf("("));
        String variable_row_count = tb_list_name.substring(tb_list_name.indexOf("(") + 1, tb_list_name.indexOf(")"));
        
        int row_count = new Integer(variable_row_count);
        List<XWPFTableRow> rows = table.getRows();
        int org_begin_index = begin_index;
        int row_begin_index = begin_index + row_count + 1;
        List<Map<String, Object>> org_row_List = new ArrayList<>();
        // 读取每一行数据
        for (int i = begin_index + 1; i < row_begin_index; i++)
        {
            XWPFTableRow row = rows.get(i);
            Map<String, Object> map = new HashMap<>();
            map.put("row", row);
            org_row_List.add(map);
        }
        int new_row_count = 0;
        // 循环
        for (int i = 0; i < tbList.size(); i++)
        {
        	// 判断
            if (i > 0 && !tb_name.endsWith("N"))
            {
                addBlankRow(table);
                new_row_count++;
            }

            Map<String, Object> rowDataMap = tbList.get(i);
            // 循环
            for (int k = 0; k < org_row_List.size(); k++)
            {
                Map<String, Object> rowMap = org_row_List.get(k);
                XWPFTableRow row = table.insertNewTableRow(row_begin_index);
                row_begin_index = row_begin_index + 1;
                new_row_count++;
                CopytTableRow(row, (XWPFTableRow) rowMap.get("row"));
                List<XWPFTableCell> cells = row.getTableCells();
                // 循环
                for (int j = 0; j < cells.size(); j++)
                {
                    XWPFTableCell cell = cells.get(j);
                    try
                    {
                        processParagraphs(cell.getParagraphs(), rowDataMap);
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                    // 判断
                    if (i != 0 && no_copy_cell.indexOf("" + j) > -1)
                    {
                    	// 循环
                        for (XWPFParagraph sp : cell.getParagraphs())
                        {
                        	// 循环
                            for (XWPFRun s : sp.getRuns())
                            {
                                s.setText("", 0);
                            }
                        }

                    }
                }
            }

        }
        // 循环
        for (int i = org_begin_index + row_count; i >= org_begin_index; i--)
        {
            new_row_count--;
            table.removeRow(i);
        }
        return new_row_count;
    }

    /** 
     * 关闭输入流 
     * 
     * @param is 
     */
    private static void close(InputStream is)
    {
    	// 判断
        if (is != null)
        {
            try
            {
                is.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    /** 
     * 关闭输出流 
     * 
     * @param os 
     */
    private static void close(OutputStream os)
    {
    	// 判断
        if (os != null)
        {
            try
            {
                os.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    /**
     * 
      * @Title: CopyRun
      * @Description: CopyRun
      * @param @param target
      * @param @param source
      * @return void
      * @author: wangyihan
      * @time: 2020年9月17日 下午1:27:32
      * history:
      * 1、2020年9月17日 下午1:27:32 wangyihan 创建方法
      *
     */
    private static void CopyRun(XWPFRun target, XWPFRun source)
    {
        target.getCTR().setRPr(source.getCTR().getRPr());
        // 设置文本
        target.setText(source.getText(0));
    }

    /**
     * 
      * @Title: copyParagraph
      * @Description: copyParagraph
      * @param @param target
      * @param @param source
      * @return void
      * @author: wangyihan
      * @time: 2020年9月17日 下午1:27:39
      * history:
      * 1、2020年9月17日 下午1:27:39 wangyihan 创建方法
      *
     */
    private static void copyParagraph(XWPFParagraph target, XWPFParagraph source)
    {
        // 设置段落样式
        target.getCTP().setPPr(source.getCTP().getPPr());
        // 添加Run标签
        for (int pos = 0; pos < target.getRuns().size(); pos++)
        {
            target.removeRun(pos);
        }
        // 循环
        for (XWPFRun s : source.getRuns())
        {
            XWPFRun targetrun = target.createRun();
            CopyRun(targetrun, s);
        }
    }

    /**
     * 
      * @Title: copyTableCell
      * @Description: copyTableCell
      * @param @param target
      * @param @param source
      * @return void
      * @author: wangyihan
      * @time: 2020年9月17日 下午1:27:54
      * history:
      * 1、2020年9月17日 下午1:27:54 wangyihan 创建方法
      *
     */
    private static void copyTableCell(XWPFTableCell target, XWPFTableCell source)
    {
        // 列属性
        target.getCTTc().setTcPr(source.getCTTc().getTcPr());
        // 删除目标 targetCell 所有单元格
        for (int pos = 0; pos < target.getParagraphs().size(); pos++)
        {
            target.removeParagraph(pos);
        }
        // 添加段落
        for (XWPFParagraph sp : source.getParagraphs())
        {
            XWPFParagraph targetP = target.addParagraph();
            copyParagraph(targetP, sp);
        }
    }

    /**
     * 
      * @Title: CopytTableRow
      * @Description: CopytTableRow
      * @param @param target
      * @param @param source
      * @return void
      * @author: wangyihan
      * @time: 2020年9月17日 下午1:28:03
      * history:
      * 1、2020年9月17日 下午1:28:03 wangyihan 创建方法
      *
     */
    private static void CopytTableRow(XWPFTableRow target, XWPFTableRow source)
    {
        // 复制样式
        target.getCtRow().setTrPr(source.getCtRow().getTrPr());
        // 复制单元格
        for (int i = 0; i < source.getTableCells().size(); i++)
        {
        	
        	// 判断
            if (target.getCell(i) == null)
            {
                target.addNewTableCell();
            }
            copyTableCell(target.getCell(i), source.getCell(i));
        }
    }

    /**
     * 
     * @Title: addBlankRow
     * @Description: 表格中插入空白行，没有左右边框
     * @param table 
     * @author: Guanxu
     * @time:2018年3月21日 下午3:26:47
     * history:
     * 1、2018年3月21日 Guanxu 创建方法
     */
    private static void addBlankRow(XWPFTable table)
    {
        XWPFTableRow blank_row = table.createRow();
        List<XWPFTableCell> blank_cells = blank_row.getTableCells();
        // 循环
        for (int j = 0; j < blank_cells.size(); j++)
        {
            XWPFTableCell cell = blank_cells.get(j);
            CTTc cttc = cell.getCTTc();
            CTTcPr ctPr = cttc.isSetTcPr() ? cttc.getTcPr() : cttc.addNewTcPr();
            CTTcBorders cell_border = ctPr.addNewTcBorders();
            CTBorder left_border = cell_border.addNewLeft();
            // 去掉单元格左右边框
            left_border.setSz(BigInteger.ONE);
            CTBorder right_border = cell_border.addNewRight();
            // 去掉单元格左右边框
            right_border.setSz(BigInteger.ONE);

        }
    }
    
    
	
}
